<!--
 * @Date: 2023-01-11 20:40:56
 * @LastEditTime: 2023-03-31 16:27:13
 * @FilePath: /NLK/src/components/common/CrequestList/CrequestList.vue
 * 介绍:列表组件
-->
<script lang="ts" setup name="List">
import usePaging from "@@/hooks/usePagingRequest";
import RpullRefresh from "@@/components/rework/RpullRefresh/RpullRefresh.vue";

const props = withDefaults(defineProps<Props_info>(), {
  minHeight: "70vh",
  pullRefresh: true,
  transitionGroup: "CrequestList",
});
interface Props_info {
  minHeight?: string;
  /**api接口 */
  api: Function;
  /**发起请求前 */
  reqBefore?: (pgae: number) => any;
  sticky?: "sticky" | "fixed";
  /**是否非分页接口 */
  onePage?: boolean;
  /**是否使用下拉刷新 */
  pullRefresh?: boolean;
  transitionGroup?: string | false;
  offsetTop?: StrNumber;
}
const {
  apiData,
  apiState,
  apiRequest,
  apiReset,
  stateEnd,
  stateErr,
  stateLoading,
  stateNull,
  stateVoid,
} = usePaging(props.api, props.reqBefore, { onePage: props.onePage });

const emit = defineEmits(["scroll", "load", "reset"]);
function load() {
  emit("load");
  apiRequest();
}

/**下拉刷新 */
const PullRefreshRef = ref<InstanceType<typeof RpullRefresh>>();
/**监听下拉刷新 */
async function onRefresh() {
  emit("reset");
  pullDownStart();
  const res = await apiReset();
  if (res.type === "err") return pullDownFail();
  pullDownSuccess();
}
/**下拉刷新成功 */
function pullDownSuccess() {
  PullRefreshRef.value?.success();
}
/**下拉刷新开始 */
function pullDownStart() {
  PullRefreshRef.value?.start();
}
/**下拉刷新失败 */
function pullDownFail() {
  PullRefreshRef.value?.fail();
}
/**暴露分页hooks */
defineExpose({
  apiReset,
  apiState,
  apiData,
  stateEnd,
  stateErr,
  stateLoading,
  stateNull,
  stateVoid,
});

let container: HTMLElement;
if (props.sticky == "fixed") container = document.documentElement;
</script>
<template>
  <div class="CrequestList">
    <div
      v-if="props.sticky == 'sticky'"
      :style="{ top: offsetTop }"
      class="CrequestList_header"
    >
      <slot name="header"></slot>
    </div>
    <van-sticky
      v-else-if="props.sticky == 'fixed'"
      :container="container"
      :offset-top="props.offsetTop"
      position="top"
    >
      <slot name="header"></slot>
    </van-sticky>
    <slot v-else name="header"></slot>

    <RpullRefresh
      :disabled="!props.pullRefresh"
      ref="PullRefreshRef"
      @refresh="onRefresh"
    >
      <van-list
        :loading="apiState.type === 'loading'"
        :finished="apiState.type === 'end' || apiState.type === 'null'"
        :error="apiState.type === 'err'"
        @load="load"
        class="CrequestList_list"
        :style="{ minHeight: props.minHeight }"
      >
        <slot>
          <div class="CrequestList_default">
            <!-- 循环渲染 -->
            <TransitionGroup
              v-if="props.transitionGroup"
              :name="props.transitionGroup"
            >
              <slot
                v-for="(item, index) in apiData"
                :key="item.id || index"
                name="item"
                :item="item"
                :index="index"
              >
              </slot>
            </TransitionGroup>
            <slot
              v-else
              v-for="(item, index) in apiData"
              :key="item.id || index"
              name="item"
              :item="item"
              :index="index"
            >
            </slot>
          </div>
        </slot>
        <template #error>
          <ClistState :type="apiState.type" :message="apiState.message" />
        </template>
        <template #finished>
          <ClistState :type="apiState.type" :message="apiState.message" />
        </template>
      </van-list>
    </RpullRefresh>
  </div>
</template>

<style lang="less" scoped>
.CrequestList {
  .CrequestList_list {
    overflow-y: auto;

    & > * + * {
      margin-top: var(--gap-md);
    }
  }
  .CrequestList_header {
    position: sticky;
    z-index: 10;
  }
  .CrequestList_default {
    margin-bottom: var(--gap-md);
  }
}
</style>
